package models;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Embedded;
import javax.persistence.Id;

import play.Logger;
import play.modules.m4fcity.M4FCityApiService;
import play.modules.m4fcity.M4FCityProfile;
import play.modules.m4fcity.OrganizationCity;
import play.modules.market.MarketProfile;
import play.mvc.Scope.Session;
import utils.constants.SessionConstants;

import com.google.appengine.api.datastore.QueryResultIterator;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;

public class User extends AbstractBaseModel {
	static {
        ObjectifyService.register(User.class);
    }

	
	@Id private Long id;
    
    @Embedded
    private Profile profile;
    
    private List<String> roles;
    
    private Boolean access;
    
    /*@Filter("owner")
    public Query<Focus> focuses;*/
   
    public User() {
            this.access = false;
            this.roles = new ArrayList<String>();
            this.profile = new Profile();   
    }
     
    public User(Profile profile) {
            this();
            this.profile = profile;
            this.access = profile.isManager();
    }
    
    
    public static Query<User> all() {
    	return getService().query(User.class);
    }
    
    public static List<User> getAll() {
    	return all().list();
    }
    
    public static User findByProfileId(String profileId) {
    	User user = all().filter("profile.id =", profileId).get();
    	
    	return user;
    }
    
    public static User findByProfileEmail(String profileType, String email) {
    	
    	User user = all().filter("profile.type =", profileType).filter("profile.email =", email).get();
    	
    	return user;
    }
    
    public static User getById(Long id) {
    	try {
    		return getService().get(new Key(User.class, id));
    	} catch(NotFoundException e) {
    		return null;
    	}
	}
    
    public static User getById(String id) {
    	try {
    		return getById(Long.parseLong(id));
	    } catch(NumberFormatException e) {
            Logger.error("Fail converting the user id from String to Long: ", e.getMessage());
            return null;
	    }
	}
    
    public static User getByKey(Key key) {
		
			return getService().get(key);
		
	}
    
    public void addFocus(Focus focus) {
    	focus.setOwner(this);
    	//focus.save();
    }
    
    public Query<Focus> ownedFocus() {
    	return Focus.all().filter("owner", this);
    }
    
    public List<Focus> getOwnedFocusList() {
    	ArrayList<Focus> list = new ArrayList<Focus>();
    	QueryResultIterator<Focus> focuses = ownedFocus().iterator();
    	while(focuses.hasNext()) list.add(focuses.next());
    	return list;
    }
            
    // GETTERS AND SETTERS
    public Long getId() {
            return id;
    }

    public void setId(Long id) {
            this.id = id;
    }
    
    public Profile getProfile() {
            return profile;
    }

    public void setProfile(Profile profile) {
            this.profile = profile;
    }

    public List<String> getRoles() {
            return roles;
    }

    public void setRoles(List<String> roles) {
            this.roles = roles;
    }
    
    public Boolean hasAccess() {
            return this.access;
    }
    
    public void setAccess(Boolean access) {
            this.access = access;
    }

 // To use in m4fcity-api module
    public static void findForM4FCityOAuth(M4FCityProfile profile){
        User user = findByProfileId(Profile.M4FCITY_PREFIX+profile.getId());
        if(user == null) {
                Logger.info("Creating new user from m4fcity: ", user);
                user = new User(new Profile(profile));
        } else {
                Logger.info("Found user from m4fcity: %s", user.getProfile().getId());
                user.setProfile(new Profile(profile));
        }
        try {
                // TODO set the namespace to the domain
                //String domain = Session.current().get(SessionConstants.DOMAIN);
                //NamespaceManager.set(domain);
                
                // Save the user
                user.save();
                
        } catch(Exception e) {
                e.printStackTrace();
        }
            
        OrganizationCity orgCity = M4FCityApiService.gerOrganization(user.getProfile().getAccessToken());
        // *** INFO For Secure.Security ***
        Session.current().put(SessionConstants.USER, user.getId());
        Session.current().put(SessionConstants.DOMAIN, orgCity.getDomain());
    }
    
    public static void findForMarketOAuth(MarketProfile profile) {
        //User user = findByProfileId(Profile.MARKET_PREFIX+profile.getId());
        User user = findByProfileEmail(Profile.MARKET_PREFIX, profile.getUserName()+"@"+profile.getDomain());
        
        if(user == null) {
                Logger.info("Creating new user from market: ", profile.getId());
                user = new User(new Profile(profile));
        } else {
                Logger.info("Found user from market: %s", user.getProfile().getId());
                user.setProfile(new Profile(profile));
                if(!user.hasAccess()) user.setAccess(user.profile.isManager()); // Update always access flag with manager flag from profile.
        }
        try {   
        //String domain = Session.current().get(SessionConstants.DOMAIN);
                //NamespaceManager.set(domain);
                
                // Save the user
                user.save();
        } catch(Exception e) {
                e.printStackTrace();
        }
        
        // TODO set the namespace to the domain
        // *** INFO For Secure.Security ***
		Session.current().put(SessionConstants.USER, user.getId());
		Session.current().put(SessionConstants.DOMAIN, user.getProfile().getDomain());
    }
}
